再推荐几个好用的pandas函数,继续加快你数据处理的速度
大家好,可以叫我才哥。
上次我们介绍了几个pandas函数,如nlargest()
、pct_change()
和explode()
,《学会这些好用的pandas函数,让你的数据处理更快人一步》让大家可以更快的求取前N组数据、计算数据之间变化率以及将列表元素数据展开为一列等等。
今天,我们再介绍几个好用的pandas函数,让大家在新增数据列、数据筛选或进行数据微调的时候继续快人一步。
目录:
1. 为Dataframe新增数据列
1.1. assign()
1.2. eval()
2. 数据筛选
3. 数据微调
1. 为Dataframe新增数据列
新增数据列其实是很常见的操作,一般情况下我们可以采用直接赋值法,也就是在原来的Dataframe数据上进行直接操作,比如:
>>> import pandas as pd
>>> df = pd.DataFrame({'temp_c': [17.0, 25.0]},
... index=['Portland', 'Berkeley'])
>>> df
temp_c
Portland 17.0
Berkeley 25.0
# 直接赋值法,新增一列
>>> df['temp_f'] = ['f1','f2']
>>> df
temp_c temp_f
Portland 17.0 f1
Berkeley 25.0 f2
# 直接赋值法,修改已有列数据
>>> df['temp_c'] = [100,200]
>>> df
temp_c temp_f
Portland 100 f1
Berkeley 200 f2
当然,我这里自然不是简单的说 直接赋值法这种操作,所以我们来看看直接赋值法可能带来的问题:
如果我们想保留原有的df,新增一个df1并在新的df1上进行有关操作,直接赋值法可能会导致修改df1的时候df也发生变化的情况
>>> df1 = df
>>> df1['A'] = '直接赋值'
>>> df1
temp_c temp_f A
Portland 100 f1 直接赋值
Berkeley 200 f2 直接赋值
>>> df
temp_c temp_f A
Portland 100 f1 直接赋值
Berkeley 200 f2 直接赋值
上述这种情况,一般我们可以通过df1=df.copy()
解决(深拷贝和浅拷贝的差异),具体这里不展开。
>>> df1=df.copy() # 深拷贝
>>> df1['A'] = '直接赋值'
>>> df1
temp_c temp_f A
Portland 100 f1 直接赋值
Berkeley 200 f2 直接赋值
>>> df
temp_c temp_f
Portland 100 f1
Berkeley 200 f2
1.1. assign()
这个时候,我们就要介绍assign()
方法了,它并不是在原来的Dataframe上进行操作,而是返回一个含原来Dataframe全部数据和新增列的Dataframe对象。
>>> df = pd.DataFrame({'temp_c': [17.0, 25.0]},
... index=['Portland', 'Berkeley'])
>>> df
temp_c
Portland 17.0
Berkeley 25.0
# 新增一列数据c
>>> df.assign(c= ['100','200'])
temp_c c
Portland 17.0 100
Berkeley 25.0 200
它还支持调用函数的方式进行赋值:
>>> df.assign(temp_f= lambda x: x.temp_c * 9 / 5 + 32)
temp_c temp_f
Portland 17.0 62.6
Berkeley 25.0 77.0
也支持直接引用现有数据列进行相关操作:
>>> df.assign(temp_f= df['temp_c'] * 9 / 5 + 32)
temp_c temp_f
Portland 17.0 62.6
Berkeley 25.0 77.0
关键它还支持同时进行多个数据列的新增处理:
>>> df.assign(temp_f= lambda x: x['temp_c'] * 9 / 5 + 32,
... temp_k= lambda x: (x['temp_f'] + 459.67) * 5 / 9)
temp_c temp_f temp_k
Portland 17.0 62.6 290.15
Berkeley 25.0 77.0 298.15
1.2. eval()
eval()
是pandas里的顶层函数,有着很牛批的作用。我们在之前《推荐几个好用的python内置函数》里关于字符串操作里介绍过python内置函数eval()
,其作用是接受字符串参数,并返回该字符串的求值结果,其实在这里也差不多,具体见下面案例介绍。
比如,我们将两列的值相加:
>>> df = pd.DataFrame({'A': range(1, 6), 'B': range(10, 0, -2)})
>>> df
A B
0 1 10
1 2 8
2 3 6
3 4 4
4 5 2
>>> df.eval('A+B')
0 11
1 10
2 9
3 8
4 7
dtype: int64
>>> df['A']+df['B']
0 11
1 10
2 9
3 8
4 7
dtype: int64
所以,基于上述,我们可以进行新增列的操作:
>>> df.eval('C= A+B')
A B C
0 1 10 11
1 2 8 10
2 3 6 9
3 4 4 8
4 5 2 7
>>> df
A B
0 1 10
1 2 8
2 3 6
3 4 4
4 5 2
# 在原数据集上进行操作
>>> df.eval('C= A+B',inplace= True)
>>> df
A B C
0 1 10 11
1 2 8 10
2 3 6 9
3 4 4 8
4 5 2 7
同样,我们也可以新增多列:
>>> df.eval(
... '''
... C = A + B
... D = A - B
... '''
... )
A B C D
0 1 10 11 -9
1 2 8 10 -6
2 3 6 9 -3
3 4 4 8 0
4 5 2 7 3
需要注意的是,eval()
只能对列进行操作,不能对元素或者行进行操作。
当然了,eval()
还支持通过 @ 符号使用 Python 的局部变量 ,@ 符号表示“这是一个变量名称而不是一个列名”,从而让你灵活地用两个“命名空间”的资源(列名的命名空间和 Python 对象的命名空间)计算代数式。
>>> df
A B C
0 1 10 11
1 2 8 10
2 3 6 9
3 4 4 8
4 5 2 7
>>> max = df.A.max()
>>> max
5
# 通过 @ 符号使用 Python 的局部变量
>>> df.eval('D = A + @max')
A B C D
0 1 10 11 6
1 2 8 10 7
2 3 6 9 8
3 4 4 8 9
4 5 2 7 10
2. 数据筛选
关于更多的数据筛选大家可以参考之前的文章《Pandas学习笔记03-数据清洗(通过索引选择数据)》,这里介绍的是query()
,一个也是接收字符串表达式参数,然后返回满足条件的数据部分的方法,据说它的性能更高。
>>> df = pd.DataFrame({'A': range(1, 6),
... 'B': range(10, 0, -2),
... 'C C': range(10, 5, -1)})
>>> df
A B C C
0 1 10 10
1 2 8 9
2 3 6 8
3 4 4 7
4 5 2 6
# 返回A列中值大于B列的数据
# 等效于 df[df.A > df.B]
>>> df.query('A>B')
A B C C
4 5 2 6
# 都会B列中值等于C C列的数据
# 等效于 df[df.B == df['C C']]
>>> df[df.B == df['C C']]
A B C C
0 1 10 10
更多表达式方式大家可以自行测试
3. 数据微调
这里介绍的是replace()
方法,将原有数据中特定的数据用指定的数据进行替换。
replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method='pad')
场景很多,比如指定的A用B替换,特定的某些数据用另外一组数据替换,满足条件的某些数据用另外的数据替换等等。
指定的A用B替换:
>>> s = pd.Series([0, 1, 2, 3, 4])
>>> s
0 0
1 1
2 2
3 3
4 4
dtype: int64
>>> s.replace(0,5)
0 5
1 1
2 2
3 3
4 4
dtype: int64
>>> df = pd.DataFrame({'A': [0, 1, 2, 3, 4],
... 'B': [5, 6, 7, 8, 9],
... 'C': ['a', 'b', 'c', 'd', 'e']})
>>> df
A B C
0 0 5 a
1 1 6 b
2 2 7 c
3 3 8 d
4 4 9 e
>>> df.replace(0, 5)
A B C
0 5 5 a
1 1 6 b
2 2 7 c
3 3 8 d
4 4 9 e
指定某些数据用另外一组数据替换
将被替换的数用放在列表里或者用字典进行对应等(注意看案例演示)
>>> df
A B C
0 0 5 a
1 1 6 b
2 2 7 c
3 3 8 d
4 4 9 e
# 一组值用另外一个值替换【列表】
>>> df.replace([0, 1, 2, 3], 4)
A B C
0 4 5 a
1 4 6 b
2 4 7 c
3 4 8 d
4 4 9 e
# 一组值用另外一组值替换,一一对应【列表】
>>> df.replace([0, 1, 2, 3], [4, 3, 2, 1])
A B C
0 4 5 a
1 3 6 b
2 2 7 c
3 1 8 d
4 4 9 e
# 多个指定值用对应值替换【字典】
>>> df.replace({0: 10, 1: 100})
A B C
0 10 5 a
1 100 6 b
2 2 7 c
3 3 8 d
4 4 9 e
# 指定列的指定值用对应值替换【字典】
>>> df.replace({'A': {0: 100, 4: 400}})
A B C
0 100 5 a
1 1 6 b
2 2 7 c
3 3 8 d
4 400 9 e
我们用Series
数据演示一下参数 method
的效果:
>>> s
0 0
1 1
2 2
3 3
4 4
dtype: int64
# 将1和2用它们前面的值替换
>>> s.replace([1,2],method = 'ffill')
0 0
1 0
2 0
3 3
4 4
dtype: int64
# 将1和2用它们前面的值替换
>>> s.replace([1,2],method = 'bfill')
0 0
1 3
2 3
3 3
4 4
dtype: int64
>>> s.replace([1,3],method = 'bfill')
0 0
1 2
2 2
3 4
4 4
dtype: int64
正则替换
这则替换就是将满足正则表达式条件的元素替换为我们想要替换的值,关于替换的方式也是有很多种的,具体大家看案例:
>>> df = pd.DataFrame({'A': ['bat', 'foo', 'bait'],
... 'B': ['abc', 'bar', 'xyz']})
>>> df
A B
0 bat abc
1 foo bar
2 bait xyz
# 将ba开头的元素替换为 new
>>> df.replace(to_replace=r'^ba.$', value='new', regex=True)
A B
0 new abc
1 foo new
2 bait xyz
# 将A列中ba开头的元素替换为 new
>>> df.replace({'A': r'^ba.$'}, {'A': 'new'}, regex=True)
A B
0 new abc
1 foo bar
2 bait xyz
# 同第一种方法
>>> df.replace(regex=r'^ba.$', value='new')
A B
0 new abc
1 foo new
2 bait xyz
# 同时进行多组不同值替换为不同的值
>>> df.replace(regex={r'^ba.$': 'new', 'foo': 'xyz'})
A B
0 new abc
1 xyz new
2 bait xyz
# 同时进行多组不同组值替换为同一个值
>>> df.replace(regex=[r'^ba.$', 'foo'], value='new')
A B
0 new abc
1 new new
2 bait xyz
以上 就是本次全部内容了,节假日学习来吧~
当然了,要是出门玩的还是尽情happy吧,哈哈!
--推荐阅读--